package main

import (
	"fmt"
	"sort"
)

type Point struct {
	X int
	Y int
	V int
}
type Array struct {
	X      int
	Y      int
	Points []Point
}

func (a *Array) Print() {
	for i := 0; i < a.X; i++ {
		for j := 0; j < a.Y; j++ {
			fmt.Printf("%d ", a.Get(i, j))
		}
		fmt.Printf("\n")
	}
}
func (a *Array) Init(points []Point) {
	a.Points = []Point{}
	for i := 0; i < a.X; i++ {
		for j := 0; j < a.Y; j++ {
			a.Points = append(a.Points, Point{i, j, 0})
		}
	}
	for _, point := range points {
		a.Set(point.X, point.Y, point.V)
	}
}
func (a *Array) Get(x, y int) int {
	if x >= 0 && x < a.X && y >= 0 && y < a.Y {
		return a.Points[x*a.Y+y].V
	}
	return -1
}
func (a *Array) Set(x, y, v int) {
	if x >= 0 && x < a.X && y >= 0 && y < a.Y {
		a.Points[x*a.Y+y].V = v
		//fmt.Printf("debug:set x=%d,y=%d,v=%d,index=%d.v=%d\n", x, y, v, x*a.X+y, a.Get(x, y))
		//a.Print()
	}
}

type Points []Point

func (ps Points) Len() int {
	return len(ps)
}
func (ps Points) Less(i, j int) bool {
	return ps[i].V > ps[j].V
}
func (ps Points) Swap(i, j int) {
	ps[i], ps[j] = ps[j], ps[i]
}

func (a *Array) Compute(points []Point) {
	var ps Points
	ps = points
	sort.Sort(ps)
	for _, point := range ps {
		a.compute1(point.X, point.Y, point.V)
	}
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}
func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}
func (a *Array) compute1(x, y, v int) {
	fmt.Printf("debug:compute point x=%d,y=%d,v=%d\n", x, y, v)
	for i := 0; i < a.X; i++ {
		for j := 0; j < a.Y; j++ {
			v0 := a.Get(i, j)
			//fmt.Printf("debug:before x=%d,y=%d,v=%d,i=%d,j=%d,v:=%d\n", x, y, v, i, j, v0)
			a.Set(i, j, max(v0, v-max(abs(x-i), abs(y-j))))
			//fmt.Printf("debug:after: x=%d,y=%d,v=%d,i=%d,j=%d,v:=%d\n", x, y, v, i, j, a.Get(i, j))

		}
	}
}

func main() {
	m, n := 5, 6
	points := []Point{Point{0, 0, 5}, Point{1, 1, 3}, Point{2, 4, 3}, Point{3, 5, 4}, Point{4, 5, 4}}
	array := &Array{X: m, Y: n}
	fmt.Println("===========init==========")
	array.Init(points)
	array.Print()
	array.Compute(points)
	fmt.Println("===========result==========")
	array.Print()

}
